/**
  ******************************************************************************
  * @file    template.c
  * @author  Iron
  * @date    2022-01-01
  * @version v1.0
  * @brief   template c file
  */

/** @addtogroup GROUP_TEMPLATE
  * @{
  */

/* Private includes ----------------------------------------------------------*/
#include <stdio.h>
#include "contiki.h"
#include "contiki-net.h"
#include "sys/node-id.h"
#include "sys/autostart.h"
#include "sys/process.h"
#include "sys/procinit.h"
#include "sys/etimer.h"
#include "sys/rtimer.h"
#include "sys/ctimer.h"
#include "sys/clock.h"
#include "sys/energest.h"
#include "dev/watchdog.h"

/* Private define ------------------------------------------------------------*/
#define DEBUG 1
#if DEBUG
    #include <stdio.h>
    #define PRINTF(...) printf(__VA_ARGS__)
#else
    #define PRINTF(...)
#endif

/* Private macro -------------------------------------------------------------*/
/* Private typedef -----------------------------------------------------------*/
/* Private variables ---------------------------------------------------------*/
unsigned int idle_count = 0;
unsigned short node_id = 0;

/* Private function prototypes -----------------------------------------------*/
void platform_init_stage_one(void);
void platform_init_stage_two(void);
void platform_init_stage_three(void);
void platform_idle();

/*---------------------------------------------------------------------------*/
void
node_id_restore(void)
{
    uint8_t uid[8];

    GetUniqueID(uid);

    node_id = uid[0] | uid[1] << 8;
}

/*---------------------------------------------------------------------------*/
void
node_id_burn(unsigned short id)
{

}

/*---------------------------------------------------------------------------*/
int main()
{
    platform_init_stage_one();

    clock_init();
    rtimer_init();
    process_init();
    process_start(&etimer_process, NULL);
    ctimer_init();
    watchdog_init();

    energest_init();

#if STACK_CHECK_ENABLED
    stack_check_init();
#endif

    platform_init_stage_two();

#if QUEUEBUF_ENABLED
    queuebuf_init();
#endif /* QUEUEBUF_ENABLED */

    netstack_init();

    // node-id
    node_id_restore();

    PRINTF("Starting " CONTIKI_VERSION_STRING "\n");
    PRINTF("TARGET=%s", CONTIKI_TARGET_STRING);
#ifdef CONTIKI_BOARD_STRING
    PRINTF(", BOARD=%s", CONTIKI_BOARD_STRING);
#endif
    PRINTF("\n");
//  PRINTF("- Routing: %s\n", NETSTACK_ROUTING.name);
    PRINTF("- Net: %s\n", NETSTACK_NETWORK.name);
    PRINTF("- MAC: %s\n", NETSTACK_MAC.name);
    PRINTF("- 802.15.4 PANID: 0x%04x\n", IEEE802154_PANID);
#if MAC_CONF_WITH_TSCH
    PRINTF("- 802.15.4 TSCH default hopping sequence length: %u\n", (unsigned)sizeof(TSCH_DEFAULT_HOPPING_SEQUENCE));
#else /* MAC_CONF_WITH_TSCH */
//  PRINTF("- 802.15.4 Default channel: %u\n", IEEE802154_DEFAULT_CHANNEL);
#endif /* MAC_CONF_WITH_TSCH */

    PRINTF("Node ID: %u\n", node_id);

#if LINKADDR_SIZE == 2
    {
        uint8_t *addr = &linkaddr_node_addr.u8[0];
        PRINTF("Link-layer address:%02x:%02x\n", addr[0], addr[1]);
    }
#endif
    
#if LINKADDR_SIZE == 8
    {
        uint8_t *addr = &linkaddr_node_addr.u8[0];
        PRINTF("Link-layer address:%02x:%02x:%02x:%02x:%02x:%02x:%02x:%02x\n",
               addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], addr[6], addr[7]);
    }
#endif 

#if NETSTACK_CONF_WITH_IPV4 || NETSTACK_CONF_WITH_IPV6

    memcpy(&uip_lladdr.addr, &linkaddr_node_addr, sizeof(uip_lladdr.addr));

    process_start(&tcpip_process, NULL);

#if NETSTACK_CONF_WITH_IPV6
    {
        uip_ds6_addr_t *lladdr;

        lladdr = uip_ds6_get_link_local(-1);

        PRINTF("Tentative link-local IPv6 address: ");
        if (lladdr != NULL)
        {
            uint8_t *addr = &lladdr->ipaddr.u8[0];
            PRINTF("%02x%02x:%02x%02x:%02x%02x:%02x%02x"
                   ":%02x%02x:%02x%02x:%02x%02x:%02x%02x",
                   addr[0], addr[1], addr[2], addr[3], 
                   addr[4], addr[5], addr[6], addr[7],
                   addr[8], addr[9], addr[10], addr[11],
                   addr[12], addr[13], addr[14], addr[15]);
            PRINTF("\n");
        }
        else
        {
            PRINTF("NULL\n");
        }
    }
#endif

#endif /* NETSTACK_CONF_WITH_IPV6 */

    platform_init_stage_three();

#if BUILD_WITH_RPL_BORDER_ROUTER
    rpl_border_router_init();
    LOG_DBG("With RPL Border Router\n");
#endif /* BUILD_WITH_RPL_BORDER_ROUTER */

#if BUILD_WITH_ORCHESTRA
    orchestra_init();
    LOG_DBG("With Orchestra\n");
#endif /* BUILD_WITH_ORCHESTRA */

#if BUILD_WITH_SHELL
    serial_shell_init();
    LOG_DBG("With Shell\n");
#endif /* BUILD_WITH_SHELL */

#if BUILD_WITH_COAP
    coap_engine_init();
    LOG_DBG("With CoAP\n");
#endif /* BUILD_WITH_SHELL */

#if BUILD_WITH_SNMP
    snmp_init();
    LOG_DBG("With SNMP\n");
#endif /* BUILD_WITH_SNMP */

#if BUILD_WITH_SIMPLE_ENERGEST
    simple_energest_init();
#endif /* BUILD_WITH_SIMPLE_ENERGEST */

#if BUILD_WITH_TSCH_CS
    /* Initialize the channel selection module */
    tsch_cs_adaptations_init();
#endif /* BUILD_WITH_TSCH_CS */

    autostart_start(autostart_processes);

    watchdog_start();

#if !(PLATFORM_PROVIDES_MAIN_LOOP)
    while (1)
    {
        uint8_t r;
        do
        {
            r = process_run();
            watchdog_periodic();
        }
        while (r > 0);

        platform_idle();
    }
#else
    platform_main_loop();
    return 0;
#endif
}


/**
  * @}
  */

/******************* (C)COPYRIGHT 2022 ***** END OF FILE *********************/
